package com.ocom.payhandle.controller;

import com.ocom.common.constant.PayHandleUrl;
import com.ocom.common.dto.MqPaymentCallBackDto;
import com.ocom.common.dto.TimerPaymentCallBackDto;
import com.ocom.common.entity.access.EntityDeptInfo;
import com.ocom.common.entity.card.EntityConsTypeConfig;
import com.ocom.common.entity.card.EntityXfAccountInfo;
import com.ocom.common.entity.card.EntityXfRecordProcess;
import com.ocom.common.entity.human.EntityPersonnelInfo;
import com.ocom.common.entity.pay.EntityAbnormal;
import com.ocom.common.enums.ResultEnum;
import com.ocom.common.request.payhandle.GetNotsendRecordRequest;
import com.ocom.common.request.payhandle.GetRecordByOrderNoRequest;
import com.ocom.common.request.payhandle.ZkzlPayRequest;
import com.ocom.common.resp.Result;
import com.ocom.common.utils.DateUtils;
import com.ocom.common.utils.ResultUtil;
import com.ocom.payhandle.feign.MqSubsidyFeign;
import com.ocom.payhandle.service.*;
import com.ocom.redis.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@RefreshScope
@Slf4j
@RestController
public class ZkzlController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());


    @Autowired
    DeviceInfoService deviceInfoService;

    @Autowired
    XfPointInfoService xfPointInfoService;

    @Autowired
    XfChannelInfoService xfChannelInfoService;

    @Autowired
    private XfRecordProcessService xfRecordProcessService;

    @Resource
    private RedisUtil redisUtil;


    @Autowired
    private XfAccountInfoService xfAccountInfoService;

    @Autowired
    private PersonnelInfoService personnelInfoService;

    @Autowired
    private DeptInfoService deptInfoService;

    @Autowired
    private XfDiscountConfigServcie xfDiscountConfigServcie;

    @Autowired
    private XfUserparamConfigService xfUserparamConfigService;

    @Autowired
    private ConsTypeConfigService consTypeConfigService;

    @Autowired
    private AbnormalService abnormalService;

    @Autowired
    private MqSubsidyFeign mqSubsidyFeign;


    //中卡智磊
    @PostMapping(PayHandleUrl.getZkzlPay)
    public Result zkzlPay(@RequestBody ZkzlPayRequest request) {
        try {
            logger.info("进入zkzlPay---------------参数：" + request.toString());

            String deviceNo = "ZKZL";
            String deviceName = "中卡水控";
            if (redisUtil.lock(request.getTradeNo(), 3 * 24 * 60 * 60)) {
                logger.info("redis加锁成功---------------TradeNo：" + request.getTradeNo());
                //3.用账号查询账号表和人员的信息
                EntityPersonnelInfo entityPersonnelInfo = personnelInfoService.selectPersonnel(request.getCompanyId(), request.getUserId());
                EntityXfAccountInfo entityXfAccountInfo = xfAccountInfoService.selectAccountPid(request.getCompanyId(), request.getUserId());
                if (entityXfAccountInfo == null || entityPersonnelInfo == null || entityXfAccountInfo.getAccountState() != 0 || entityPersonnelInfo.getStatus() != 0) {
                    //异常单处理
                    logger.info("异常单处理---------------OrderNo" + request.getTradeNo());
                    EntityXfRecordProcess entityXfRecordProcess = new EntityXfRecordProcess();
                    entityXfRecordProcess.setComId(request.getCompanyId());
                    entityXfRecordProcess.setDeviceNo(deviceNo);
                    entityXfRecordProcess.setDeviceName(deviceName);
                    entityXfRecordProcess.setPointId(0L);
                    entityXfRecordProcess.setPointName("");//TODO
                    entityXfRecordProcess.setMerchId(0L);
                    entityXfRecordProcess.setMerchName("");//TODO
                    entityXfRecordProcess.setPId(request.getUserId());
                    entityXfRecordProcess.setConsType(request.getConsType());
                    entityXfRecordProcess.setConsMoney(-request.getAmount().longValue());
                    entityXfRecordProcess.setConsState(1);
                    entityXfRecordProcess.setOpType(14l);
                    entityXfRecordProcess.setOpTypeDiff(100l);
                    entityXfRecordProcess.setOrderNo(request.getTradeNo());
                    entityXfRecordProcess.setPlatOrderNo(request.getTradeNo() + deviceNo);
                    entityXfRecordProcess.setPayTime(new Date());
                    entityXfRecordProcess.setPayState(2);
                    entityXfRecordProcess.setSendState(0);
                    entityXfRecordProcess.setCreateTime(new Date());

                    int i = xfRecordProcessService.insertEntityXfRecord(request.getCompanyId(), entityXfRecordProcess);
                    if (i <= 0) {
                        log.info("请求方式:【{}】,机器号:【{}】,请求参数:【{}】,返回:【{}】", "支付请求（强在线）", request.getMachineId(), request, ResultUtil.error(ResultEnum.Err_802));
                        //订单号重复
                        return ResultUtil.error(ResultEnum.Err_4112);
                    }

                } else {
                    logger.info("查询扣款顺序---------------");

                    //查询扣款顺序
                    EntityConsTypeConfig entityConsTypeConfig = consTypeConfigService.selectEntityConsTypeConfig(request.getCompanyId(), request.getConsType());

                    int payState = 0;
                    String walletSerial = "21";

                    //字符串：空表示不允许使用虚拟账户扣款,扣款顺序（1现金钱包、2补贴钱包）
                    if (entityConsTypeConfig != null) {
                        if (entityConsTypeConfig.getWalletSerial() != null) {
                            walletSerial = entityConsTypeConfig.getWalletSerial();
                            logger.info("walletSerial---------------：" + walletSerial);
                        }
                    }

                    //判断扣款
                    int consMoney = -request.getAmount();
                    Date date = new Date();
                    int intMealNo = 0;

                    EntityXfRecordProcess entityXfRecordProcess = new EntityXfRecordProcess();
                    entityXfRecordProcess.setComId(request.getCompanyId());
                    entityXfRecordProcess.setDeviceNo(deviceNo);
                    entityXfRecordProcess.setDeviceName(deviceName);
                    entityXfRecordProcess.setPointId(0L);
                    entityXfRecordProcess.setPointName("");
                    entityXfRecordProcess.setMerchId(0L);
                    entityXfRecordProcess.setMerchName("");
                    entityXfRecordProcess.setDeptId(entityPersonnelInfo.getDeptId());
                    EntityDeptInfo entityDeptInfo = deptInfoService.selectDeptName(request.getCompanyId(), entityPersonnelInfo.getDeptId());
                    if (entityDeptInfo != null) {
                        entityXfRecordProcess.setDeptName(entityDeptInfo.getDeptName());
                    }
                    entityXfRecordProcess.setPId(request.getUserId());
                    entityXfRecordProcess.setPCode(entityPersonnelInfo.getPCode());
                    entityXfRecordProcess.setPName(entityPersonnelInfo.getPName());
                    entityXfRecordProcess.setAccountNo(entityXfAccountInfo.getAccountNo());

                    entityXfRecordProcess.setConsTime(DateUtils.strToDate(request.getTradeTime()));
                    entityXfRecordProcess.setMealNo("0");
                    entityXfRecordProcess.setMealDate(DateUtils.strToDate2(request.getTradeTime()));
                    entityXfRecordProcess.setConsType(request.getConsType());

                    int discount = xfDiscountConfigServcie.selectSiscount(request.getCompanyId(), entityXfAccountInfo.getPId(),
                            entityXfAccountInfo.getAccTypeId(), request.getConsType(), date, intMealNo, request.getAmount(), entityXfRecordProcess);
                    consMoney = entityXfRecordProcess.getConsMoney().intValue();
                    int realMoney = consMoney + discount;
                    entityXfRecordProcess.setDiscount(Long.valueOf(discount));


                    int limit = xfUserparamConfigService.selectLimit(request.getCompanyId(), entityXfAccountInfo.getPId(),
                            entityXfAccountInfo.getAccTypeId(), request.getConsType(), date, intMealNo, (Math.abs(realMoney)),false);
                    if (limit != 0) {
                        if (limit == 1) {
                            return ResultUtil.error(ResultEnum.Err_4031);
                        } else if (limit == 2) {
                            return ResultUtil.error(ResultEnum.Err_4032);
                        }
                        if (limit == 3) {
                            return ResultUtil.error(ResultEnum.Err_4033);
                        }
                        if (limit == 4) {
                            return ResultUtil.error(ResultEnum.Err_4034);
                        }
                        if (limit == 5) {
                            return ResultUtil.error(ResultEnum.Err_4035);
                        }
                        if (limit == 6) {
                            return ResultUtil.error(ResultEnum.Err_4036);
                        }
                    }

                    entityXfRecordProcess.setConsMoney(Long.valueOf(consMoney));

                    entityXfRecordProcess.setRealMoney(Long.valueOf(realMoney));

                    entityXfRecordProcess.setConsState(1);//消费状态，1：消费；2：退款；3：点餐；4.取餐；5.订餐；6：退订；10：充值；11：提现；12：补贴；13：清卡；21：销户
                    entityXfRecordProcess.setOpType(14l);
                    entityXfRecordProcess.setOpTypeDiff(100l);
                    entityXfRecordProcess.setOrderNo(request.getTradeNo());
                    entityXfRecordProcess.setPlatOrderNo(request.getTradeNo() + deviceNo);
                    entityXfRecordProcess.setPayTime(new Date());
                    entityXfRecordProcess.setPayState(0);
                    entityXfRecordProcess.setSendState(0);
                    entityXfRecordProcess.setCreateTime(new Date());

                    //0、如果扣费通道opTypeDiff等于0，或者实际消费金额realAmount等于0：
                    if (entityXfRecordProcess.getOpTypeDiff() == null && entityXfRecordProcess.getRealMoney() != 0) {
                        if (walletSerial.equals("")) {
                            entityXfRecordProcess.setChargeMoney(0L);
                            entityXfRecordProcess.setSubMoney(Long.valueOf(consMoney));
                        } else if (walletSerial.equals("1")) {
                            //现金钱包
                            entityXfRecordProcess.setChargeMoney(entityXfRecordProcess.getRealMoney());
                            entityXfRecordProcess.setSubMoney(0L);
                        } else if (walletSerial.equals("2")) {
                            //补贴钱包
                            entityXfRecordProcess.setSubMoney(entityXfRecordProcess.getRealMoney());
                            entityXfRecordProcess.setChargeMoney(0L);
                        } else if (walletSerial.equals("21")) {
                            //先扣补贴钱包，再扣现金钱包
                            if (entityXfAccountInfo.getAccountSubsidyMoney() >= entityXfRecordProcess.getRealMoney()) {
                                entityXfRecordProcess.setSubMoney(entityXfRecordProcess.getRealMoney());
                                entityXfRecordProcess.setChargeMoney(0L);
                            } else if (entityXfAccountInfo.getAccountSubsidyMoney() > 0) {
                                entityXfRecordProcess.setSubMoney(-entityXfAccountInfo.getAccountSubsidyMoney());
                                entityXfRecordProcess.setChargeMoney(entityXfRecordProcess.getRealMoney() + entityXfAccountInfo.getAccountSubsidyMoney());
                            } else {
                                entityXfRecordProcess.setSubMoney(0l);
                                entityXfRecordProcess.setChargeMoney(entityXfRecordProcess.getRealMoney());
                            }

                        } else {
                            //先扣现金钱包，再扣补贴钱包
                            if (entityXfAccountInfo.getAccountRechargeMoney() >= entityXfRecordProcess.getRealMoney()) {
                                entityXfRecordProcess.setChargeMoney(entityXfRecordProcess.getRealMoney());
                                entityXfRecordProcess.setSubMoney(0L);
                            } else if (entityXfAccountInfo.getAccountRechargeMoney() > 0) {
                                entityXfRecordProcess.setChargeMoney(-entityXfAccountInfo.getAccountRechargeMoney());
                                entityXfRecordProcess.setSubMoney(entityXfRecordProcess.getRealMoney() + entityXfAccountInfo.getAccountRechargeMoney());
                            } else {
                                entityXfRecordProcess.setChargeMoney(0l);
                                entityXfRecordProcess.setSubMoney(entityXfRecordProcess.getRealMoney());
                            }
                        }
                    } else {
                        entityXfRecordProcess.setChargeMoney(0L);
                        entityXfRecordProcess.setSubMoney(Long.valueOf(consMoney));
                    }
                    entityXfRecordProcess.setChargeBalance(entityXfAccountInfo.getAccountRechargeMoney() + entityXfRecordProcess.getChargeMoney());
                    entityXfRecordProcess.setSubBalance(entityXfAccountInfo.getAccountSubsidyMoney() + entityXfRecordProcess.getSubMoney());

                    try {
                        logger.info("insertEntityXfRecord---------------OrderNo:" + request.getTradeNo());

                        int i = xfRecordProcessService.insertEntityXfRecord(request.getCompanyId(), entityXfRecordProcess);
                        if (i <= 0) {
                            log.info("请求方式:【{}】,机器号:【{}】,请求参数:【{}】,返回:【{}】", "支付请求（强在线）", request.getMachineId(), request, ResultUtil.error(ResultEnum.Err_802));
                            //订单号重复
                            return ResultUtil.error(ResultEnum.Err_4112);
                        }
                    } catch (Exception e) {
                        StackTraceElement ste = e.getStackTrace()[0];
                        log.info("请求方式:【{}】,机器号:【{}】,入库新增等待表的数据:【{}】,异常的返回:【{}】,行号:【{}】", "支付请求（强在线）", request.getMachineId(), entityXfRecordProcess, e, ste.getLineNumber());
                        log.info("请求方式:【{}】,机器号:【{}】,请求参数:【{}】,返回:【{}】", "支付请求（强在线）", request.getMachineId(), request, ResultUtil.error(ResultEnum.Err_802));
                        //订单号重复
                        return ResultUtil.error(ResultEnum.Err_4112);
                    }
                    try {

                        EntityXfRecordProcess updateXfRecordProcess = new EntityXfRecordProcess();
                        updateXfRecordProcess.setPayState(1);
                        updateXfRecordProcess.setPayTime(new Date());
                        updateXfRecordProcess.setId(entityXfRecordProcess.getId());

                        entityXfRecordProcess.setPayState(1);
                        entityXfRecordProcess.setPayTime(updateXfRecordProcess.getPayTime());
                        entityXfRecordProcess.setId(null);
                        try {
                            logger.info("updateAccountTransactional---------------Id:" + entityXfAccountInfo.getId());

                            xfAccountInfoService.updateAccountTransactional(request.getCompanyId(), entityXfAccountInfo.getId(), entityXfRecordProcess, updateXfRecordProcess);
                        } catch (Exception e) {
                            StackTraceElement ste = e.getStackTrace()[0];
                            log.info("请求方式:【{}】,机器号:【{}】,修改金额的事务:【{}】,异常的返回:【{}】,行号:【{}】", "支付请求（保存消费记录）", request.getMachineId(), entityXfRecordProcess, e, ste.getLineNumber());
                            return ResultUtil.error(ResultEnum.Err_4112);
                        }

                    } catch (Exception e) {
                        StackTraceElement ste = e.getStackTrace()[0];
                        log.info("请求方式:【{}】,机器号:【{}】,入库新增等待表的数据:【{}】,异常的返回:【{}】,行号:【{}】", "支付请求（强在线）", request.getMachineId(), entityXfRecordProcess, e, ste.getLineNumber());
                        log.info("请求方式:【{}】,机器号:【{}】,请求参数:【{}】,返回:【{}】", "支付请求（强在线）", request.getMachineId(), request, ResultUtil.error(ResultEnum.Err_802));
                        //订单号重复
                        return ResultUtil.error(ResultEnum.Err_4112);
                    }
                }

            } else {
                //修改分库临时表xf_record_process中order_no匹配的记录的已推送字段，改为未推送
                //返回1
                logger.info("修改分库临时表xf_record_process中order_no匹配的记录的已推送字段，改为未推送---------------tradeNo:" + request.getTradeNo());

                EntityXfRecordProcess entityXfRecordProcess = xfRecordProcessService.selectTradeNo(request.getCompanyId(), request.getTradeNo(), deviceNo);
                if (null == entityXfRecordProcess) {
                    return ResultUtil.error(ResultEnum.Err_4112);
                }
                entityXfRecordProcess.setSendState(0);
                xfRecordProcessService.updateById(entityXfRecordProcess);

            }

            logger.info("推送MQ_sendMsg---------------tradeNo:" + request.getTradeNo());
            //MQ
            MqPaymentCallBackDto callBackVo = new MqPaymentCallBackDto();
            callBackVo.setComId(request.getCompanyId());
            callBackVo.setPId(request.getUserId());
            callBackVo.setTradeNo(request.getTradeNo());
            mqSubsidyFeign.sendMsg(callBackVo);

        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtil.error(ResultEnum.Err_4112);
        }
        return ResultUtil.success();
    }

    @PostMapping(PayHandleUrl.getZkzlTimer)
    public void zkzlTimerPaymentCallBack(@RequestBody TimerPaymentCallBackDto dto) {
        List<EntityXfRecordProcess> list = xfRecordProcessService.getNotsendRecord(dto.getComId(), "ZK", null, null, dto.getAutoSize());

        for (EntityXfRecordProcess entiy : list) {
            //MQ
            MqPaymentCallBackDto callBackVo = new MqPaymentCallBackDto();
            callBackVo.setComId(entiy.getComId());
            callBackVo.setPId(entiy.getPId());
            callBackVo.setTradeNo(entiy.getOrderNo());
            mqSubsidyFeign.sendMsg(callBackVo);
        }

    }

    @PostMapping(PayHandleUrl.URL_getRecordByOrderno)
    public Result getRecordByOrderno(@RequestBody GetRecordByOrderNoRequest request) {
        EntityXfRecordProcess entiyXfRecordProcess = xfRecordProcessService.getRecordByOrderno(request.getCompanyId(), request.getPId(), request.getOrderNo());
        return ResultUtil.success(entiyXfRecordProcess);
    }

    @PostMapping(PayHandleUrl.URL_sendByOrderno)
    public Result sendByOrderno(@RequestBody EntityXfRecordProcess request) {

        return ResultUtil.success(xfRecordProcessService.sendByOrderno(request.getComId(), request.getOrderNo()));
    }

    @PostMapping(PayHandleUrl.URL_getNotsendRecord)
    public Result getNotsendRecord(@RequestBody GetNotsendRecordRequest request) {

        return ResultUtil.success(xfRecordProcessService.getNotsendRecord(request.getCompanyId(), request.getPrefix(), request.getConsStates(), request.getPayState(), request.getSize()));
    }

    @PostMapping(PayHandleUrl.URL_addAbnormal)
    public Result addAbnormal(@RequestBody EntityAbnormal request) {
        return ResultUtil.success(abnormalService.Add(request.getComId(), request));
    }

}
